"""
Grave! Important! Важно!

Proletoj el ĉiuj landoj, unuiĝu!
Workers of the world, unite!
Пролетарии всех стран, соединяйтесь!

https://tkom.pro
"""

from django.utils.deprecation import MiddlewareMixin
from django.utils.http import http_date
from django.conf import settings
from django.contrib import auth
from django.contrib.auth.models import AnonymousUser
import asyncio

from siriuso.utils import get_token_session
from importlib import import_module

import time


def get_uzanto(request):
    uzanto = None

    for backend_path in settings.AUTHENTICATION_BACKENDS:
        backend = auth.load_backend(backend_path)
        try:
            uzanto = backend.authenticate(request)
            if uzanto:
                setattr(uzanto, 'backend', backend)
                break
        except:
            pass
    return uzanto or AnonymousUser()


class SiriusoUzantoTokenAuth(MiddlewareMixin):
    sync_capable = True
    async_capable = True

    def __init__(self, get_response=None):
        self.get_response = get_response
        engine = import_module(settings.SESSION_ENGINE)
        self.SessionStore = engine.SessionStore
        self._async_check()

    def _async_check(self):
        """
        If get_response is a coroutine function, turns us into async mode so
        a thread is not consumed during a whole request.
        """
        if asyncio.iscoroutinefunction(self.get_response):
            # Mark the class as async-capable, but do the actual switch
            # inside __call__ to avoid swapping out dunder methods
            self._is_coroutine = asyncio.coroutines._is_coroutine

    def process_request(self, request):
        if hasattr(request, 'META') and 'HTTP_X_AUTH_TOKEN' in request.META:
            # проверяем что бы не было в url пути для jwt - в этом случае авторизация должна быть по JWT
            if ('/jwt/' in request.META.get('PATH_INFO').lower()):
                return
            token = request.META.get('HTTP_X_AUTH_TOKEN')
            session_key = get_token_session(token)

            if session_key:
                request.COOKIES[settings.SESSION_COOKIE_NAME] = session_key

    def process_response(self, request, response):
        if hasattr(request, 'META') and 'HTTP_X_AUTH_TOKEN' in request.META:
            token = request.META.get('HTTP_X_AUTH_TOKEN')
            session_key = get_token_session(token)

            if session_key:
                if response.status_code != 500:
                    if request.session.get_expire_at_browser_close():
                        max_age = None
                        expires = None
                    else:
                        max_age = request.session.get_expiry_age()
                        expires_time = time.time() + max_age
                        expires = http_date(expires_time)

                    response.set_cookie(
                        settings.SESSION_COOKIE_NAME,
                        request.session.session_key, max_age=max_age,
                        expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
                        path=settings.SESSION_COOKIE_PATH,
                        secure=settings.SESSION_COOKIE_SECURE or None,
                        httponly=settings.SESSION_COOKIE_HTTPONLY or None,
                        samesite=settings.SESSION_COOKIE_SAMESITE,
                    )

        return response
